﻿#region using
using MpSoft.IO;
using System;
using System.Collections.Generic;
using System.IO;
#endregion using

namespace PdbRestorer.Engine
{
	public class SimplePdbFile
	{
		string _filename;
		Stream _stream;
		List<ulong> _poss=new List<ulong>();

		public SimplePdbFile(string filename)
		{
			_filename=filename;
		}

		public SimplePdbFile(Stream file)
		{
			_stream=file;
		}

		public bool Read(out Guid signature,out int age)
		{
			byte[] streamSignature=BitConverter.GetBytes((int)0x01312E94);

			//because I can't supress "The out parameter 'XXX' must be assigned to before control leaves the current method" compiler error message
			signature=default(Guid);
			age=default(int);

			Stream stream=_stream??File.OpenRead(_filename);
			bool found=false;
			try
			{
				ulong pos,lastPos=0;
				int toFindLen=streamSignature.Length;
				while (stream.Find(streamSignature,out pos))
				{
					pos+=lastPos;
					_poss.Add(pos+8);
					lastPos=pos+(ulong)toFindLen;

					if (!found)
					{
						found=true;
						byte[] buffer=new byte[16];
						if (stream.Read(buffer,0,8)!=8)
							throw new EndOfStreamException();
						age=BitConverter.ToInt32(buffer,4);
						if (stream.Read(buffer,0,16)!=16)
							throw new EndOfStreamException();
						signature=new Guid(buffer);
						lastPos+=24;
					}
				}
			}
			finally
			{
				if (_stream==null)
					stream.Close();
			}

			/*if (!found)
			{
				 signature=default(Guid);
				 age=default(int);
			}*/
			return found;
		}

		public bool Write(Guid signature,int age)
		{
			if (_poss.Count==0)
				return false;

			Stream stream=_stream??File.OpenWrite(_filename);
			try
			{
				foreach (int pos in _poss)
				{
					stream.Seek(pos,SeekOrigin.Begin);
					stream.Write(BitConverter.GetBytes(age),0,4);
					stream.Write(signature.ToByteArray(),0,16);
				}
			}
			finally
			{
				if (_stream==null)
					stream.Close();
			}
			return true;
		}
	}
}
